﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Sharp.Domain;
using Sharp.Domain.Model;
using Sharp.Infrastructure;

namespace Sharp.Application
{
    public static class RepositoryExtension
    {
        private static readonly string[] IgnoreFields;


        static RepositoryExtension()
        {
            IgnoreFields = new[]
            {
                nameof(ILogCreatedEntity.CreatedTime),
                nameof(ILogCreatedEntity.CreatedUserId),
                nameof(ILogModifiEntity.ModifiTime),
                nameof(ILogModifiEntity.ModifiedUserId),
                nameof(ILogDeleteEntity.DeleteUserId),
                nameof(ILogDeleteEntity.DeleteTime),
                //nameof(IFilter4Org.OrgId),
                nameof(IStandardState.EntityState),
                nameof(IEntity.Id)
            };
        }

        /// <summary>
        /// 自动更新字段的值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="rep"></param>
        /// <param name="aggregateRoot">新的数据</param>
        /// <returns></returns>
        /// <remarks>可能会因为关闭延迟加载功能而导致一些字段没有更新</remarks>
        public static IRepository<TKey, TEntity> AutoUpdateFields<TKey, TEntity>(this IRepository<TKey, TEntity> rep,
            TEntity aggregateRoot)
            where TKey : struct
            where TEntity : class, IAggregateRoot<TKey>
        {
            TEntity info = rep.Get(aggregateRoot.Id);

            FillField(aggregateRoot, info);

            return rep;
        }

        /// <summary>
        /// 填充字段的值
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        private static void FillField(object source, object target)
        {
            if (target == null)
            {
                return;
            }
            var properties = target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

            foreach (var property in properties)
            {
                if (IgnoreFields.Any(x => x == property.Name))
                    continue;

                if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
                {
                    property.SetValue(target, property.GetValue(source));
                }
                else
                {
                    //FillField(property.GetValue(source), property.GetValue(target));
                }

            }
        }
    }
}
